﻿using CleanArchitecture.Core.Configuration;
using CleanArchitecture.Core.Interfaces;
using CleanArchitecture.Infrastructure.Entities;
using CleanArchitecture.Infrastructure.Entities.Business;
using Microsoft.AspNetCore.Http;
using System.Collections.Generic;
using System.IO;

namespace CleanArchitecture.Infrastructure.Interfaces.Media
{
    /// <summary>
    /// FileUpload service interface
    /// 首先明确设计思路：
    ///     本地存储一律除了保留文件在本地服务器文件夹外，还要保留二进制数据到数据库中
    ///     如果文件大小超过数据字段允许最大值，则保存至云存储
    ///     云存储文件只保留上传链接记录，二进制字段不保存
    ///     
    /// 上传时只存储文件数据表，不存储文件到文件系统，获取时更新数据到文件系统
    /// </summary>
    public partial interface IFileUploadService
    {
        /// <summary>
        /// Returns the file extension from mime type.
        /// </summary>
        /// <param name="mimeType">Mime type</param>
        /// <returns>File extension</returns>
        string GetFileExtensionFromMimeType(string mimeType);
        /// <summary>
        /// Gets the loaded File binary depending on File storage settings
        /// </summary>
        /// <param name="file">file</param>
        /// <returns>FileUpload binary</returns>
        byte[] LoadFileBinary(FileUpload file);

        /// <summary>
        /// Get file SEO friendly name
        /// </summary>
        /// <param name="name">Name</param>
        /// <returns>Result</returns>
        string GetFileSeName(string name);

        /// <summary>
        /// Gets the default file URL
        /// </summary>
        /// <param name="targetSize">The target file size (longest side) 当filetype为image时用，指定图片长度比例</param>
        /// <param name="defaultFileType">Default file type</param>
        /// <returns>File URL</returns>
        string GetDefaultFileUrl(FileType defaultFileType = FileType.Image, int targetSize = 0);

        /// <summary>
        /// Get a fileupload URL
        /// </summary>
        /// <param name="fileuploadId">Picture identifier</param>
        /// <param name="targetSize">The target file size (longest side)</param>
        /// <param name="showDefaultPicture">A value indicating whether the default picture is shown</param>
        /// <returns>fileupload URL</returns>
        string GetFileUrl(int fileuploadId,
            int targetSize = 0,
            bool showDefaultPicture = true);

        /// <summary>
        /// Get a file URL
        /// </summary>
        /// <param name="fileupload">fileupload instance</param>
        /// <param name="targetSize">The target file size (longest side)</param>
        /// <param name="showDefaultPicture">A value indicating whether the default picture is shown</param>
        /// <returns>FileUpload URL</returns>
        string GetFileUrl(FileUpload file,
            int targetSize = 0,
            bool showDefaultPicture = true);

        /// <summary>
        /// Gets a file
        /// </summary>
        /// <param name="fileuploadId">FileUpload identifier</param>
        /// <returns>FileUpload</returns>
        FileUpload GetFileUploadEntityById(int fileId);

        /// <summary>
        /// Gets FileUploads by id array
        /// </summary>
        /// <param name="Ids"></param>
        /// <returns></returns>
        IList<FileUpload> GetFileUploadList(int[] Ids);
        /// <summary>
        /// Deletes a file
        /// </summary>
        /// <param name="file">FileUpload</param>
        void DeleteFileUploadEntity(FileUpload file);

        /// <summary>
        /// Gets a collection of Uploaded files
        /// </summary>
        /// <param name="fileType">fileType</param>
        /// <param name="virtualPath">Virtual path</param>
        /// <param name="pageIndex">Current page</param>
        /// <param name="pageSize">Items on each page</param>
        /// <returns>Paged list of </returns>
        IViewPagedList<FileUpload> GetFileList(FileType[] fileTypes = null, int pageIndex = 0, int pageSize = int.MaxValue);

        /// <summary>
        /// Inserts a File
        /// 如果存储是云存储，则不用保存文件二进制
        /// </summary>
        /// <param name="fileType">The file type</param>
        /// <param name="mimeType">The file MIME type</param>
        /// <param name="category">The use type of upload file</param>
        /// <param name="seoFilename">The SEO filename</param>
        /// <param name="altAttribute">"alt" attribute for "img" HTML element</param>
        /// <param name="titleAttribute">"title" attribute for "img" HTML element</param>
        /// <param name="virtualpath">virtualpath</param>
        /// <param name="isNew">A value indicating whether the picture is new</param>
        /// <param name="fileBinary">The file binary, if store to cloud, then do not insert file binary</param>
        /// <param name="storeType">a value indicating file store to local or to Cloud</param>
        /// <returns>FileUpload</returns>
        FileUpload InsertFileEntity(FileType fileType, string mimeType, string category, string seoFilename, string altAttribute = null, string titleAttribute = null,
            bool isNew = true, string virtualpath = "", byte[] fileBinary = null, EntityEnumConfig.FileStoreType storeType = EntityEnumConfig.FileStoreType.LocalStorage, string linkUrl = null);

        /// <summary>
        /// Inserts a File 从上传文件类型自动检测文件类型
        /// 如果存储是云存储，则不用保存文件二进制
        /// </summary>
        /// <param name="formFile">Form file</param>
        /// <param name="category">the use type of file</param>
        /// <param name="virtualPath">Virtual path</param>
        /// <param name="storeType">a value indicating file store to local or to Cloud</param>
        /// <returns>FileUpload</returns>
        FileUpload InsertFileEntity(IFormFile formFile, string category, string virtualPath = "",
                              EntityEnumConfig.FileStoreType storeType = EntityEnumConfig.FileStoreType.LocalStorage);

        /// <summary>
        /// Updates the file 
        /// </summary>
        /// <param name="fileuploadId">The file identifier</param>
        /// <param name="fileBinary">The file binary</param>
        /// <param name="seoFilename">The SEO filename</param>
        /// <param name="altAttribute">"alt" attribute for "img" HTML element</param>
        /// <param name="titleAttribute">"title" attribute for "img" HTML element</param>
        /// <param name="isNew">A value indicating whether the picture is new</param>
        /// <returns>FileUpload</returns>
        FileUpload UpdateFileEntityWithBinary(int fileuploadId, byte[] fileBinary, string seoFilename, string altAttribute = null, 
            string titleAttribute = null, bool isNew = true);

        FileUpload UpdateFileEntityWithBinary(FileUpload file, string oldFileName = "");

        /// <summary>
        /// Updates the File 
        /// 只更新文件记录，适用于云存储
        /// </summary>
        /// <param name="file">The file to update</param>
        /// <returns>FileUpload</returns>
        FileUpload UpdateFileEntityOnly(FileUpload file);

        /// <summary>
        /// Updates the downloadcount of a file
        /// </summary>
        /// <param name="fileuploadId">The fileupload identifier</param>
        /// <returns>FileUpload</returns>
        FileUpload SetFileDownloadCount(int fileuploadId);

        /// <summary>
        /// Validates input picture dimensions
        /// </summary>
        /// <param name="pictureBinary">Picture binary</param>
        /// <param name="mimeType">MIME type</param>
        /// <returns>Picture binary or throws an exception</returns>
        byte[] ValidatePictureDimension(byte[] pictureBinary, string mimeType);
        /// <summary>
        /// 只针对图片的上传图片并存储
        /// </summary>
        /// <param name="pictures"></param>
        /// <param name="storeType"></param>
        /// <returns>返回图片保存本地或云端后的存储路径</returns>
        //IList<string> UploadPictures(IFormFileCollection pictures, EntityEnumConfig.FileStoreType storeType);
        /// <summary>
        /// Gets or sets a value indicating whether the images should be stored in data base.
        /// </summary>
        //bool StoreInDb { get; set; }

        /// <summary>
        /// Get pictures hashes
        /// </summary>
        /// <param name="picturesIds">Pictures Ids</param>
        /// <returns></returns>
        IDictionary<int, string> GetPicturesHash(int[] picturesIds);
        /// <summary>
        /// 对文件存储的虚拟路径分组获得所有存储路径及路径下对应的文件数量
        /// </summary>
        /// <returns></returns>
        IDictionary<string, int> GetVirtualDirectories(string[] usecategories);
        
    }
}
